home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1996
/
MacHack 1996.toast
/
Presentations
/
Presentations ’93
/
Macintosh as Internet Server ƒ
/
inetd
/
UDP.cp
< prev
next >
Wrap
Text File
|
1993-04-27
|
5KB
|
259 lines
#include "UDP.h"
#include "InetD.h"
#include <UFailure.h>
#include <myUtils.h>
#include <Resources.h>
#include <Devices.h>
#include <Processes.h>
#include <Desk.h>
UDPListener::UDPListener(InetD* daemon)
{
fDaemon = daemon;
}
UDPListener::~UDPListener()
{
this->Release();
}
Boolean
UDPListener::Initialize()
{
int numPBs;
int i;
Handle resHandle;
short theID;
ResType theType;
Str255 theName;
numPBs = CountResources('UDP ');
if (numPBs > 0) {
for (i = 1; i <= numPBs; i++) {
resHandle = GetIndResource('UDP ', i);
FailResError();
GetResInfo(resHandle, &theID, &theType, theName);
this->ListenOn((udp_port) theID);
ReleaseResource(resHandle);
}
return true;
}
else
return false;
}
void
UDPListener::DoNull()
{
PortItem* item;
Handle resHandle;
FailInfo fi;
while ((item = (PortItem*) fLaunchList.First()) != nil) {
resHandle = GetResource('UDP ', item->fPort);
FailResError();
HLock(resHandle);
fDaemon->LogIt(false, "Attempting to launch %P\n", ((FSSpec*) *resHandle)->name);
if (fi.Try()) {
fDaemon->Launch(item->fStream, (FSSpec*) *resHandle, 'USTR', &item->fPSN);
fi.Success();
}
else {
this->CloseDown(item->fStream);
fDaemon->LogIt(true, "InetD:\n\nFailed to launch %P for UDP port %d",
((FSSpec*) *resHandle)->name, item->fPort);
}
fLaunchList.TakeOff(item);
fRestartList.PutOn(item);
HUnlock(resHandle);
ReleaseResource(resHandle);
}
}
void
UDPListener::ListenOn(udp_port thePort)
{
UDPiopb pb;
Ptr rcvPtr = nil;
PortItem* nu;
rcvPtr = NewPtrSys(4 * 1024);
FailMemError();
pb.ioCompletion = nil;
pb.csCode = UDPCreate;
pb.ioCRefNum = fDaemon->GetDriver();
pb.csParam.create.rcvBuff = rcvPtr;
pb.csParam.create.rcvBuffLen = 4 * 1024;
pb.csParam.create.localPort = thePort;
pb.csParam.create.notifyProc = &UDPNotify;
pb.csParam.create.userDataPtr = (Ptr) this;
FailOSErr(PBControlSync((ParmBlkPtr) &pb));
nu = new PortItem;
FailNIL(nu);
nu->fStream = pb.udpStream;
nu->fPort = pb.csParam.create.localPort;
nu->fDaemon = fDaemon;
fWaitList.PutOn(nu);
}
void
UDPListener::CloseDown(StreamPtr stream)
{
UDPiopb pb;
pb.csCode = UDPRelease;
pb.ioCRefNum = fDaemon->GetDriver();
pb.udpStream = stream;
FailOSErr(PBControlSync((ParmBlkPtr) &pb));
DisposePtr(pb.csParam.create.rcvBuff);
FailMemError();
}
void
UDPListener::Release()
{
PortItem* item;
while ((item = (PortItem*) fWaitList.First()) != nil) {
this->CloseDown(item->fStream);
fWaitList.TakeOff(item);
delete item;
}
while ((item = (PortItem*) fLaunchList.First()) != nil) {
this->CloseDown(item->fStream);
fLaunchList.TakeOff(item);
delete item;
}
}
void
UDPListener::NotifyMe(PSNPtr psn, StreamPtr stream, ProcPtr proc, Ptr usr)
{
PortItem* nu = new PortItem;
FailNIL(nu);
nu->fPSN.highLongOfPSN = psn->highLongOfPSN;
nu->fPSN.lowLongOfPSN = psn->lowLongOfPSN;
nu->fStream = stream;
nu->fProc = proc;
nu->fUsrPtr = usr;
fNoteeList.PutOn(nu);
}
/* These currently gets called with the PSN of every app that
we launch, even the ones that don't request ASR service,
hence its okay if the notee isn't found.
*/
void
UDPListener::UnNotify(PSNPtr psn)
{
PortItem* old;
old = fNoteeList.GetItem(psn);
if (old) {
fNoteeList.TakeOff(old);
delete old;
}
}
void
UDPListener::ListenAgain(PSNPtr psn)
{
PortItem* old;
udp_port port;
old = fRestartList.GetItem(psn);
if (old) {
fRestartList.TakeOff(old);
port = old->fPort;
delete old;
this->ListenOn(port);
}
}
PortItem::PortItem()
{
fPort = 0;
fStream = nil;
fProc = nil;
fUsrPtr = nil;
fPSN.highLongOfPSN = 0;
fPSN.lowLongOfPSN = 0;
fDaemon = nil;
}
PortItem*
UPortList::GetItem(PSNPtr psn)
{
PortItem* it = (PortItem*) this->First();
while (it && (!SameProcesses(psn, &it->fPSN)))
it = (PortItem*) it->fNext;
return it;
}
PortItem*
UPortList::GetItem(StreamPtr stream)
{
PortItem* it = (PortItem*) this->First();
while (it && (stream != it->fStream))
it = (PortItem*) it->fNext;
return it;
}
pascal void
UDPNotify( StreamPtr stream,
unsigned short eventCode,
Ptr usrData,
struct ICMPReport* icmp)
{
PortItem* them;
UDPListener* udp = (UDPListener*) usrData;
if (eventCode == UDPDataArrival) {
them = udp->fWaitList.GetItem(stream);
if (them) {
udp->fWaitList.TakeOff(them);
udp->fLaunchList.PutOn(them);
WakeUpProcess(&them->fDaemon->fPSN);
return;
}
}
/* if we get here, the event wasn't for a connection
i'm mantaining, therefore it needs to be passed
on to whoever is.
*/
them = udp->fNoteeList.GetItem(stream);
if (them && them->fProc)
(*(UDPNotifyProc) them->fProc)(stream, eventCode, them->fUsrPtr, icmp);
}